package com.itheima.sfbx.framework.aspect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itheima.sfbx.framework.anno.SensitiveResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Type;

@Component
@Aspect //标记为切面类
public class SensitiveAspect {

    //使用环绕通知拦截使用了 SensitiveResponse注解的方法
    @Around("@annotation(sensitiveResponse)")
    public Object doAround(ProceedingJoinPoint joinPoint, SensitiveResponse sensitiveResponse) throws Throwable {
        //获取方法返回值
        Object result = joinPoint.proceed();

        if(result != null){
            //将对象转换为json字符串
            String jsonString = JSONObject.toJSONString(result);

            //替换敏感数据
            String resultString = maskSensitiveData(jsonString);

            //将json字符串转换为对象
            //获取原方法的返回类型
            //获取原方法的签名
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            //获取返回类型
            Type returnType = methodSignature.getMethod().getGenericReturnType();
            return JSONObject.parseObject(resultString, returnType);
        }


        //对返回值进行脱敏处理
        return result;
    }

    /**
     * 敏感数据处理  \"(.).+?\" 表示匹配双引号内的第一个字符  $1也就是表示这第一个字符
     * @param jsonData json字符串
     * @return 处理过后的json字符串
     */
    private String maskSensitiveData(String jsonData) {
        return jsonData
                .replaceAll("\"identityCard\"\\s*:\\s*\"(\\d{1})(\\d{15})(\\d{2})\"", "\"identityCard\":\"$1**************$3\"")
                .replaceAll("\"name\"\\s*:\\s*\"(.).+?\"", "\"name\":\"$1*\"")
                .replaceAll("\"bankCardNo\"\\s*:\\s*\"(.).+?\"", "\"bankCardNo\":\"$1*\"")
                .replaceAll("\"bankName\"\\s*:\\s*\"(.).+?\"", "\"bankName\":\"$1*\"")
                .replaceAll("\"bankReservedPhoneNum\"\\s*:\\s*\"(.).+?\"", "\"bankReservedPhoneNum\":\"$1*\"");
    }
}
